#pragma once
#include <Dynamics/Pdm/pdm_cpu.h>

namespace PhysLeo {

/**
 * Peridynamics gpu model, extends the ForceModule interface.
 * implement the classical peridynamics method for simulation. Note you apply the simplified peridynamcis model by use a default simplified pdm material.
 */
template<typename T>
class PdmCuda : public PdmCpu<T> {
public:
    /**
    * empty constructor, set everything to its default value
    */
    PdmCuda();

    /**
    * allocate resource.
    * @param[in] sim_data  a data structure manage the simulation data.
    */
    void allocateResource(SimData<T>& sim_data) override;

    /**
    * return the deformation energy by PDM.
    * @param[in] ptr_pos  current position of the system
    * @return deformation energy according to current position
    */
    T deformEnergy(std::shared_ptr<BufferData<glm::tvec3<T>>> ptr_pos) override;

    /**
    * return the internal force by PDM.
    * @param[in] ptr_pos  current position of the system
    * @param[in] ptr_force  internal force of the system according to current position.
    */
    void internalForce(std::shared_ptr<BufferData<glm::tvec3<T>>> ptr_pos, std::shared_ptr<BufferData<glm::tvec3<T>>> ptr_force) override;

protected:
    /**
    * compute the volume dilation for every point according current position
    * @param[in] ptr_pos  current position of the system
    */
    void volumeDilation(std::shared_ptr<BufferData<glm::tvec3<T>>> ptr_pos) override;

    /**
    * init the ptr_weight_ according to ptr_neighborlist_, ptr_rest_pos_ and pdm_weight_type_
    */
    void initWeights() override;
 
};

}